//树节点文件
#ifndef NODE_H
#define NODE_H

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "enum.h"

#define TRUE 1
#define FALSE 0

typedef struct node {
    int lineNo;  //  行号
    NodeType type;  // 节点类型，在enum.h中有宏定义
    char* name;     //  节点名称
    char* val;      //  节点值

    struct node* child;  //  左儿子
    struct node* next;   //  右兄弟
} Node;

typedef unsigned boolean;
typedef Node* pNode;
/*inline可以把函数指定为内联函数。 这样可以解决一些频繁调用的函数大量消耗栈空间（栈内存）的问题.*/
//拷贝字符串
static inline char* newString(char* src) {
    if (src == NULL) return NULL;
    int length = strlen(src) + 1;
    char* p = (char*)malloc(sizeof(char) * length);
    strncpy(p, src, length);
    return p;
}
//创建一个节点
static inline pNode newNode(int lineNo, NodeType type, char* name, int argc,
                            ...) {
    pNode curNode = NULL;
    curNode = (pNode)malloc(sizeof(Node));

    curNode->lineNo = lineNo;
    curNode->type = type;
    curNode->name = newString(name);

    va_list vaList;
    va_start(vaList, argc);

    pNode tempNode = va_arg(vaList, pNode);//指向下一个参数的地址
    curNode->child = tempNode; //  左儿子

    for (int i = 1; i < argc; i++) {
        tempNode->next = va_arg(vaList, pNode);
        if (tempNode->next != NULL) {
            tempNode = tempNode->next;//  右兄弟
        }
    }

    va_end(vaList);//清空
    return curNode;
}
//创建一个叶子节点
static inline pNode newTokenNode(int lineNo, NodeType type, char* tokenName,
                                 char* tokenText) {
    pNode tokenNode = (pNode)malloc(sizeof(Node));

    tokenNode->lineNo = lineNo;
    tokenNode->type = type;
    tokenNode->name = newString(tokenName);
    tokenNode->val = newString(tokenText);

    tokenNode->child = NULL;
    tokenNode->next = NULL;
    return tokenNode;
}
//删除节点
static inline void delNode(pNode* node) {
    if (node == NULL) return;
    pNode p = *node;
    while (p->child != NULL) {
        pNode temp = p->child;
        p->child = p->child->next;
        delNode(&temp);
    }
    free(p->name);
    free(p->val);
    free(p);
    p = NULL;
}
#endif
